/*
 * Copyright 2025 arisgo@163.com
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.arisgo.cloud.core.utils;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.DecodedJWT;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.Map;

/**
 * @author Arisgo
 * @since 2024/1/29
 */
public class JwtUtil {

    private final static Logger logger = LoggerFactory.getLogger(JwtUtil.class);

    /**
     * jwt加签 {@link com.auth0.jwt.RegisteredClaims}
     * iss: jwt签发者，此处为 arisgo-cloud
     * sub: jwt所面向的用户，此处为 角色，普通用户，管理员或其他，可以多设
     * aud: 接收jwt的一方，此处使用username
     * jti: jwt的唯一身份标识，主要用来作为一次性token,从而回避重放攻击
     * iat: jwt的签发时间
     * nbf: 定义在什么时间之前，该jwt都是不可用的.
     * exp: jwt的过期时间，这个过期时间必须要大于签发时间
     *
     * @param secret   秘钥
     * @param exp      过期时间
     * @param payloads 加签内容，payloads中的属性会覆盖iat,nbf,exp等
     * @return token
     */
    public static String sign(String secret, long exp, Map<String, ?> payloads) {
        Instant instant = Instant.now();
        JWTCreator.Builder builder = JWT.create()
                .withIssuedAt(Date.from(instant))
                .withExpiresAt(Date.from(instant.plus(exp, ChronoUnit.HOURS)))
                .withNotBefore(Date.from(instant))
                .withPayload(payloads);
        return builder.sign(Algorithm.HMAC256(secret));
    }

    /**
     * 获取指定内容
     *
     * @param token token
     * @param key   获取内容的key
     * @return 值
     */
    public static <T> T getClaim(String token, String key, Class<T> clazz) {
        DecodedJWT jwt = JWT.decode(getToken(token));
        return jwt.getClaim(key).as(clazz);
    }

    /**
     * 验证签名是否有效，是否过期
     *
     * @param token  token
     * @param secret 秘钥
     * @return true/false
     */
    public static boolean verify(String token, String secret) {
        try {
            // 根据密码生成JWT效验器
            JWT.require(Algorithm.HMAC256(secret)).build().verify(getToken(token));
            return true;
        } catch (TokenExpiredException e) {
            logger.warn("token已过期！", e);
            return false;
        } catch (JWTVerificationException e) {
            logger.error("token验证失败！", e);
            return false;
        }
    }

    public static String getToken(String token) {
        if (token.startsWith("Bearer")) {
            return token.replaceFirst("Bearer", "").trim();
        }
        return token;
    }



    public static void main(String[] args) {
        String secret = "arisgo-cloud-secret";
        String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE3MTc5OTE1MzQsImV4cCI6MTcxNzk5ODczNCwibmJmIjoxNzE3OTk1MTM0LCJzdWIiOiJ1c2VyIiwiYXVkIjoidXNlciIsImlzcyI6IkFyaXNnb0Nsb3VkIiwidXNlciI6eyJuaWNrbmFtZSI6IuaZrumAmueUqOaItyIsInVzZXJJZCI6IjIiLCJ1c2VybmFtZSI6InVzZXIifX0.3BN8zlPlLJJZ8QLcKELlHIhUKmiMDq7mQThqvQldo1E";
        boolean verify = verify(token, secret);
        System.out.println(verify);
    }

}
